/* Copyright (C) 2005-2013, Unigine Corp. All rights reserved.
 *
 * File:    fragment_base.h
 * Desc:    Base fragment shader
 * Version: 1.09
 * Author:  Alexander Zapryagaev <frustum@unigine.com>
 *
 * This file is part of the Unigine engine (http://unigine.com/).
 *
 * Your use and or redistribution of this software in source and / or
 * binary form, with or without modification, is subject to: (i) your
 * ongoing acceptance of and compliance with the terms and conditions of
 * the Unigine License Agreement; and (ii) your inclusion of this notice
 * in any version of this software that you use or redistribute.
 * A copy of the Unigine License Agreement is available by contacting
 * Unigine Corp. at http://unigine.com/
 */

#ifndef __FRAGMENT_BASE_H__
#define __FRAGMENT_BASE_H__

/******************************************************************************\
*
* OpenGL/OpenGLES
*
\******************************************************************************/

#ifdef OPENGL || OPENGLES

/*
 */
#ifdef OPENGLES
	precision highp float;
#endif

/*
 */
#include <core/shaders/simple/common/common_base.h>

/* compatibility
 */
#if SHADING_LANGUAGE >= 150
	#define varying in
	#define gl_FragColor s_frag_color
	out fixed4 s_frag_color;
#endif

/*
 */
#ifdef HAS_EXT_SHADOW_SAMPLERS
	##extension GL_EXT_shadow_samplers : require
#endif

/* component texture sampling
 */
fixed texture2Dx(sampler2D s_texture,float2 texcoord) {
	#ifdef OPENGLES
		#ifdef USE_AMD_COMPRESSED_3DC_TEXTURE
			return texture2D(s_texture,texcoord).x;
		#elif USE_AMD_COMPRESSED_ATC_TEXTURE
			return texture2D(s_texture,texcoord).y;
		#elif HAS_EXT_TEXTURE_RG
			return texture2D(s_texture,texcoord).x;
		#else
			return texture2D(s_texture,texcoord).w;
		#endif
	#else
		return texture2D(s_texture,texcoord).x;
	#endif
}

fixed2 texture2Dxy(sampler2D s_texture,float2 texcoord) {
	#ifdef OPENGLES
		#ifdef USE_AMD_COMPRESSED_3DC_TEXTURE
			return texture2D(s_texture,texcoord).xy;
		#elif USE_AMD_COMPRESSED_ATC_TEXTURE
			return texture2D(s_texture,texcoord).yw;
		#elif HAS_EXT_TEXTURE_RG
			return texture2D(s_texture,texcoord).xy;
		#else
			return texture2D(s_texture,texcoord).xw;
		#endif
	#else
		return texture2D(s_texture,texcoord).xy;
	#endif
}
	
/* alpha test texture sampling
 */
fixed4 texture2DAlpha(sampler2D s_texture,float2 texcoord) {
	fixed4 value = texture2D(s_texture,texcoord);
	#ifdef ALPHA_TEST
		if(value.w <= 0.5f) discard;
	#endif
	return value;
}

fixed4 texture2DAlpha(sampler2D s_texture,float2 texcoord,fixed scale) {
	fixed4 value = texture2D(s_texture,texcoord);
	#ifdef ALPHA_TEST
		value.w = value.w * scale;
		if(value.w <= 0.5f) discard;
	#endif
	return value;
}

/* normal texture sampling
 */
fixed3 texture2DNormal(sampler2D s_texture,float2 texcoord) {
	#ifdef OPENGLES
		#ifdef USE_AMD_COMPRESSED_3DC_TEXTURE
			fixed3 value = texture2D(s_texture,texcoord).xyz;
		#elif USE_AMD_COMPRESSED_ATC_TEXTURE
			fixed3 value = texture2D(s_texture,texcoord).yww;
		#elif HAS_EXT_TEXTURE_RG
			fixed3 value = texture2D(s_texture,texcoord).xyz;
		#else
			fixed3 value = texture2D(s_texture,texcoord).xww;
		#endif
	#else
		fixed3 value = texture2D(s_texture,texcoord).xyz;
	#endif
	#ifndef HAS_ARB_TEXTURE_SNORM
		value.xy = value.xy * 2.0f - 1.0f;
	#endif
	value.z = sqrt(saturate(1.0f - dot(value.xy,value.xy)));
	return value;
}

/* lightmap texture sampling
 */
fixed3 texture2DLightMap(sampler2D s_texture,float2 texcoord,fixed3 normal) {
	#ifdef USE_DIRECTIONAL_LIGHTMAPS
		texcoord *= 0.5f;
		#ifdef QUALITY_MEDIUM
			fixed4 weight;
			weight.x = normal.z;
			weight.y = saturate(dot(float3(0.816496f,0.0f,0.577350f),normal));
			weight.z = saturate(dot(float3(-0.408248f, 0.707106f,0.577350f),normal));
			weight.w = saturate(dot(float3(-0.408248f,-0.707106f,0.577350f),normal));
			weight = weight * weight;
			weight = weight * weight;
			fixed3 value_0 = texture2D(s_texture,texcoord).xyz * weight.x;
			fixed3 value_1 = texture2D(s_texture,texcoord + float2(0.5f,0.0f)).xyz * weight.y;
			fixed3 value_2 = texture2D(s_texture,texcoord + float2(0.0f,0.5f)).xyz * weight.z;
			fixed3 value_3 = texture2D(s_texture,texcoord + float2(0.5f,0.5f)).xyz * weight.w;
			return (value_0 + value_1 + value_2 + value_3) / dot(weight,float4(1.0f));
		#else
			return texture2D(s_texture,texcoord).xyz;
		#endif
	#else
		return texture2D(s_texture,texcoord).xyz;
	#endif
}

/*
 */
#include <core/shaders/simple/common/deferred_base.h>
#ifdef AMBIENT || PROB || SPOT || OMNI || PROJ || WORLD
	#include <core/shaders/simple/common/fragment_base_shading.h>
#endif
#ifdef PROJ
	#include <core/shaders/simple/common/fragment_base_shadow_proj.h>
#elif AMBIENT_LIGHT || WORLD
	#include <core/shaders/simple/common/fragment_base_shadow_world.h>
#endif

/******************************************************************************\
*
* Direct3D11/Direct3D119
*
\******************************************************************************/

#elif DIRECT3D11 || DIRECT3D119

/*
 */
#include <core/shaders/simple/common/common_base.h>

/* texture samplers
 */
SamplerState s_sampler_0 : register(s0);
SamplerState s_sampler_1 : register(s1);
SamplerState s_sampler_2 : register(s2);
SamplerState s_sampler_3 : register(s3);
SamplerState s_sampler_4 : register(s4);
SamplerState s_sampler_5 : register(s5);
SamplerState s_sampler_6 : register(s6);
SamplerState s_sampler_7 : register(s7);

SamplerComparisonState s_sampler_compare_0 : register(s0);
SamplerComparisonState s_sampler_compare_1 : register(s1);
SamplerComparisonState s_sampler_compare_2 : register(s2);
SamplerComparisonState s_sampler_compare_3 : register(s3);
SamplerComparisonState s_sampler_compare_4 : register(s4);
SamplerComparisonState s_sampler_compare_5 : register(s5);
SamplerComparisonState s_sampler_compare_6 : register(s6);
SamplerComparisonState s_sampler_compare_7 : register(s7);

/* component texture sampling
 */
half texture2Dx(Texture2D s_texture,SamplerState s_sampler,float2 texcoord) {
	#ifdef HAS_FEATURE_LEVEL_10_0
		return s_texture.Sample(s_sampler,texcoord).x;
	#else
		return s_texture.Sample(s_sampler,texcoord).w;
	#endif
}

half2 texture2Dxy(Texture2D s_texture,SamplerState s_sampler,float2 texcoord) {
	#ifdef HAS_FEATURE_LEVEL_10_0
		return s_texture.Sample(s_sampler,texcoord).xy;
	#else
		return s_texture.Sample(s_sampler,texcoord).wy;
	#endif
}

/* alpha test texture sampling
 */
half4 texture2DAlpha(Texture2D s_texture,SamplerState s_sampler,float2 texcoord) {
	half4 value = s_texture.Sample(s_sampler,texcoord);
	#ifdef ALPHA_TEST
		if(value.w <= 0.5f) discard;
	#endif
	return value;
}

half4 texture2DAlpha(Texture2D s_texture,SamplerState s_sampler,float2 texcoord,half scale) {
	half4 value = s_texture.Sample(s_sampler,texcoord);
	#ifdef ALPHA_TEST
		value.w = value.w * scale;
		if(value.w <= 0.5f) discard;
	#endif
	return value;
}

/* normal texture sampling
 */
half3 texture2DNormal(Texture2D s_texture,SamplerState s_sampler,float2 texcoord) {
	#ifdef HAS_FEATURE_LEVEL_10_0
		half3 value = s_texture.Sample(s_sampler,texcoord).xyz;
	#else
		half3 value = s_texture.Sample(s_sampler,texcoord).wyy;
		value.xy = value.xy * 2.0f - 1.0f;
	#endif
	value.z = sqrt(saturate(1.0f - dot(value.xy,value.xy)));
	return value;
}

/* lightmap texture sampling
 */
half3 texture2DLightMap(Texture2D s_texture,SamplerState s_sampler,float2 texcoord,half3 normal) {
	#ifdef USE_DIRECTIONAL_LIGHTMAPS
		texcoord *= 0.5f;
		#ifdef QUALITY_MEDIUM
			half4 weight;
			weight.x = normal.z;
			weight.y = saturate(dot(half3(0.816496f,0.0f,0.577350f),normal));
			weight.z = saturate(dot(half3(-0.408248f, 0.707106f,0.577350f),normal));
			weight.w = saturate(dot(half3(-0.408248f,-0.707106f,0.577350f),normal));
			weight = weight * weight;
			weight = weight * weight;
			half3 value_0 = s_texture.Sample(s_sampler,texcoord).xyz * weight.x;
			half3 value_1 = s_texture.Sample(s_sampler,texcoord + half2(0.5f,0.0f)).xyz * weight.y;
			half3 value_2 = s_texture.Sample(s_sampler,texcoord + half2(0.0f,0.5f)).xyz * weight.z;
			half3 value_3 = s_texture.Sample(s_sampler,texcoord + half2(0.5f,0.5f)).xyz * weight.w;
			return (value_0 + value_1 + value_2 + value_3) / dot(weight,1.0f);
		#else
			return s_texture.Sample(s_sampler,texcoord).xyz;
		#endif
	#else
		return s_texture.Sample(s_sampler,texcoord).xyz;
	#endif
}

/*
 */
#include <core/shaders/simple/common/deferred_base.h>
#ifdef AMBIENT || PROB || SPOT || OMNI || PROJ || WORLD
	#include <core/shaders/simple/common/fragment_base_shading.h>
#endif
#ifdef PROJ
	#include <core/shaders/simple/common/fragment_base_shadow_proj.h>
#elif AMBIENT_LIGHT || WORLD
	#include <core/shaders/simple/common/fragment_base_shadow_world.h>
#endif

#endif

#endif /* __FRAGMENT_BASE_H__ */
